/*
 * Zenlayer.com Inc.
 * Copyright (c) 2014-2020 All Rights Reserved.
 */

package cn.xej.demo.executor;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.concurrent.Callable;

/**
 * @author wolfgang
 * @date 2020-05-15 15:31:07
 * @version $ Id: TeamSwitchExecutor.java, v 0.1  wolfgang Exp $
 */
@Component
public class TeamSwitchExecutor {

    public static String ak20;

    public static <T> T switchToTeam(Callable<T> callable, String teamUid) {
        String preTeam = TeamContext.getContext().getTeam();
        if (teamUid.equals(preTeam)) {
            try {
                return callable.call();
            } catch (RuntimeException e) {
                throw e;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        try {
            TeamContext.getContext().setTeamUid(teamUid);
            return callable.call();
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            TeamContext.getContext().setTeamUid(preTeam);
        }
    }

    public static void switchToTeam(Runnable runnable, String teamUid) {
        String preTeam = TeamContext.getContext().getTeam();
        if (teamUid.equals(preTeam)) {
            runnable.run();
            return;
        }
        try {
            TeamContext.getContext().setTeamUid(teamUid);
            runnable.run();
        } finally {
            TeamContext.getContext().setTeamUid(preTeam);
        }
    }

    public static <T> Callable<T> wrapCallable(Callable<T> callable, String teamUid) {
        return new CallableWrapper<T>(callable, teamUid);
    }

    public static Runnable wrapRunnable(Runnable runnable, String teamUid) {
        return new RunnableWrapper(runnable, teamUid);
    }

    public static void switchToAk(Runnable runnable, String ak) {
        try {
            TeamContext.getContext().setAk(ak);
            runnable.run();
        } finally {
            TeamContext.removeContext();
        }
    }

    public static void switchToDefaultAk(Runnable runnable) {
        try {
            System.out.println("TeamSwitchExecutor ak20 "+ak20);
            TeamContext.getContext().setAk(ak20);
            runnable.run();
        } finally {
            TeamContext.removeContext();
        }
    }

    public static <T> T switchToDefaultAk(Callable<T> runnable) {
        try {
            TeamContext.getContext().setAk(ak20);
            return runnable.call();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            TeamContext.removeContext();
        }
    }

    public static class CallableWrapper<T> implements Callable<T> {
        Callable<T> delegate;
        String      teamUid;

        public CallableWrapper(Callable<T> callable, String teamUid) {
            this.delegate = callable;
            this.teamUid = teamUid;
        }

        @Override
        public T call() throws Exception {
            return TeamSwitchExecutor.switchToTeam(delegate, teamUid);
        }
    }

    public static class RunnableWrapper implements Runnable {
        Runnable delegate;
        String   teamUid;

        public RunnableWrapper(Runnable runnable, String teamUid) {
            this.delegate = runnable;
            this.teamUid = teamUid;
        }

        @Override
        public void run() {
            TeamSwitchExecutor.switchToTeam(delegate, teamUid);
        }
    }

    @Autowired
    public void setAk20(@Value("${bmc.api.key.20}") String ak20) {
        TeamSwitchExecutor.ak20 = ak20;
    }
}
